import 'dart:convert';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_webrtc_client/file_channel_util.dart';
import 'package:web_socket_channel/web_socket_channel.dart';
import 'package:file_picker/file_picker.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '文件点对点传输',
      theme: ThemeData(colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple)),
      home: const MyHomePage(title: '文件点对点传输'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  //外网IP
  String ip = "114.113.116.153";
  //本地测试IP
  // String ip = "192.168.5.121";
  String port = "7424";
  final TextEditingController _controller_1 = TextEditingController();
  final TextEditingController _controller_2 = TextEditingController();
  String remotePeerId = "";
  int userId = DateTime.now().millisecondsSinceEpoch;
  late WebSocketChannel mWebSocketClient;
  final List<String> items = [];
  FileChannelUtil? mFileChannelUtil;
  String? _selectedFileName;
  Uint8List? _selectedFileBytes;

  void _listen() {
    mWebSocketClient.stream.listen(
      (data) {
        // 收到消息时的处理（onData）
        print('收到1: $data');
        try {
          if (data is String) {
            // 需要先将字符串转换为JSON对象
            Map<String, dynamic> jsonMap = json.decode(data);
            // 然后使用fromJson构造函数
            switch (jsonMap['type']) {
              case "0":
                print("服务器通知又有新客户端登陆了");
                if (jsonMap['sender'] != userId.toString()) {
                  setState(() {
                    items.add(jsonMap['sender']);
                  });
                }
                break;
              case "1":
                print("服务器通知有客户端退出");
                setState(() {
                  items.remove(jsonMap['sender']);
                });
                break;
              case 'offer':
                print("收到offer");
                mFileChannelUtil ??= FileChannelUtil(
                  sender: _controller_2.text,
                  receiver: jsonMap['sender'],
                  mWebSocketClient: mWebSocketClient,
                  onMessage: (str) {
                    print("收到消息：$str");
                    _showMessageNotification("收到消息：$str");
                  },
                  onFileReceived: (Uint8List fileBytes, String fileName) {
                    print("收到文件：$fileName (${fileBytes.length} 字节)");
                    _showMessageNotification("收到文件：$fileName (${fileBytes.length} 字节)");
                  },
                );
                mFileChannelUtil!.handleOffer(jsonMap['data']);
                break;
              case 'answer':
                print("收到answer");
                mFileChannelUtil?.handleAnswer(jsonMap['data']);
                break;
              case 'candidate':
                mFileChannelUtil ??= FileChannelUtil(
                  sender: _controller_2.text,
                  receiver: jsonMap['sender'],
                  mWebSocketClient: mWebSocketClient,
                  onMessage: (str) {
                    print("收到消息：$str");
                    _showMessageNotification("收到消息：$str");
                  },
                  onFileReceived: (Uint8List fileBytes, String fileName) {
                    print("收到文件：$fileName (${fileBytes.length} 字节)");
                    _showMessageNotification("收到文件：$fileName (${fileBytes.length} 字节)");
                  },
                );
                mFileChannelUtil?.handleCandidate(jsonMap['data']);
                break;
              default:
                print("default");
                break;
            }
          }
        } catch (e) {
          print('消息解析失败: $e');
        }
      },
      onError: (error) {
        // 发生错误时（onError）
        print('错误: $error');
      },
      onDone: () {
        // 连接关闭时（onDone）
        print('连接已关闭');
      },
      cancelOnError: false, // 是否在出错时自动取消监听
    );
  }

  @override
  void initState() {
    super.initState();
    _controller_1.text = "ws://${ip}:${port}/chat?token=";
    _controller_2.text = "${userId}";
  }

  @override
  void dispose() {
    _controller_1.dispose();
    _controller_2.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title)),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          const Text('文件点对点传输'),
          TextField(
            onChanged: (value) {
              print(_controller_1.text);
            },
            controller: _controller_1,
          ),
          TextField(
            onChanged: (value) {
              print(_controller_2.text);
            },
            controller: _controller_2,
          ),
          SizedBox(height: 10),
          ElevatedButton(
            onPressed: () async {
              mWebSocketClient = WebSocketChannel.connect(Uri.parse(_controller_1.text + _controller_2.text));
              await mWebSocketClient.ready;
              _listen();
            },
            child: Text('连接服务器'),
          ),
          SizedBox(height: 10),
          ElevatedButton(
            onPressed: () {
              print('与服务器断开连接');
              mWebSocketClient.sink.close(1000, userId.toString());
            },
            child: Text('与服务器断开连接'),
          ),
          SizedBox(height: 10),
          ElevatedButton(
            onPressed: () {
              print('服务器断开所有连接');
              mWebSocketClient.sink.add('DisconnectAllConnections');
            },
            child: Text('服务器断开所有连接'),
          ),
          SizedBox(height: 10),
          ...items.map((item) {
            return Column(
              children: [
                ElevatedButton(
                  onPressed: () {
                    print('与${item}开始连接');
                    remotePeerId = item;
                    createOffer(item);
                  },
                  child: Text(item),
                ),
                SizedBox(height: 10),
              ],
            );
          }).toList(),
          SizedBox(height: 10),
          ElevatedButton(
            onPressed: _selectFile,
            child: Text('选择文件'),
          ),
          SizedBox(height: 10),
          Text(_selectedFileName ?? '尚未选择文件'),
          SizedBox(height: 10),
          ElevatedButton(
            onPressed: _selectedFileBytes != null ? _sendFile : null,
            child: Text('发送文件'),
          ),
        ],
      ),
    );
  }

  void createOffer(String receiver) {
    mFileChannelUtil = FileChannelUtil(
      sender: _controller_2.text,
      receiver: receiver,
      mWebSocketClient: mWebSocketClient,
      onMessage: (str) {
        print("收到消息：$str");
        _showMessageNotification("收到消息：$str");
      },
      onFileReceived: (Uint8List fileBytes, String fileName) {
        print("收到文件：$fileName (${fileBytes.length} 字节)");
        _showMessageNotification("收到文件：$fileName (${fileBytes.length} 字节)");
      },
    );
    mFileChannelUtil?.createOffer();
  }

  /// 选择文件
  Future<void> _selectFile() async {
    FilePickerResult? result = await FilePicker.platform.pickFiles();
    
    if (result != null) {
      PlatformFile file = result.files.first;
      print('file.name: ${file.name}');
      print('file.size: ${file.size}');
      print('file.bytes: ${file.bytes}');
      print('file.path: ${file.path}');

      setState(() {
        _selectedFileName = file.name;
        _selectedFileBytes = file.bytes;
      });
      
      _showMessageNotification('已选择文件: ${file.name} (${file.size} 字节)');
    } else {
      // 用户取消选择
      _showMessageNotification('未选择任何文件');
    }
  }

  /// 发送文件
  void _sendFile() {
    if (_selectedFileBytes != null && _selectedFileName != null) {
      mFileChannelUtil?.sendFile(_selectedFileBytes!, _selectedFileName!);
    } else {
      _showMessageNotification('请先选择文件');
    }
  }

  /// 显示消息通知
  ///
  /// 在界面底部显示SnackBar消息通知
  ///
  /// [message] 要显示的消息内容
  void _showMessageNotification(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
        duration: const Duration(seconds: 2),
        action: SnackBarAction(
          label: '关闭',
          onPressed: () {
            // 点击动作按钮的操作
          },
        ),
      ),
    );
  }
}